; MC404 - Organizacao Basica de Computadores e Linguagem de Montagem
; Professor: Alexandro Baldassin
; Turma C
;
;  Programa em assembly (NASM) para Visualizacao de Imagens BMP 
;  Os Bitmaps devem possuir maximo de 256 cores,
;  8 bits por cor nao comprimidos
;
;  Plataforma alvo: arquivos objetos (OBJ/EXE) 16-bit (DOS)
;  OBS: montar com a opcao -fobj
;
; Desenvolvedores: Ng Kin Jin              RA 045565
;                  Tiago R C Falcão        RA 046802
;
;


SEGMENT code                ; segmento de codigo
..start:                    ; ponto de entrada do programa

  ;Salva Segmento PSP
  mov  ax, data
  mov  ds, ax
  mov [PSP],es

  ;Inicializa sistema de 2 Buffers
  mov [SEG_BUFFER],word segbuffer    ;seta segbuffer como o principal
  mov [SEG_BUFFER2],word segbuffer2  ;seta segbuffer2 como secundario

  ; inicializa pilha (SS:SP)
  mov  ax, stack
  mov  ss, ax
  mov  sp, stacktop


  ;Execucao MAIN do Programa
  call COPY_FLNAME    ;copia nome do arquivo para Memoria
  call OPENFILE       ;abre arquivo
  call IMAGEHEAD      ;Le e Avalia o HEAD do arquivo

  call GRAPHMOD       ;Seta Modo Grafico
  call SET_CURSOR

  call LOAD_MAPCOLOR  ;Le o Mapa de Cores e armazena na memoria
  call RESET_COLOR    ;Seta o Mapa dee cores no Video

  call LOADIMAGE      ;Le os Pixels Arquivo e armazena no Buffer Principal
  call RESET_POS      ;Calcula Posicões de Escrita na Tela e Copia da Imagem

  call CLOSEFILE      ;Fecha o Arquivo

  call MENU           ;Executa o Loop de Escolha de Opcões

  call TEXTMOD        ;Seta Modo Grafico
  call END            ;Finaliza Execucao

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                     FUNCOES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MENU:;************************************************************************
;Funcao de Espera de Comandos e Execucao dos Mesmos

  call SHOWIMAGE  ;Exibe/Atualiza Imagem em Tela

  MENUSI:         ;Chamada p/ MENU sem Re-Exibicao da Imagem

  ;Le Tecla
  mov ah,0x08
  int 0x21
  xor ah,ah       ;Zera AH para uma melhor avaliacao do resultado

  MENU2:          ;Chamada p/ MENU sem Re-Exibicao da Imagem e Leitura do Tecl

  or al,0x00      ;Avalia Tecla Lida Para Detectar Caracter de Controle
  jnz OPTCTRL
  ;Le Tecla
  mov ah,0x08
  int 0x21

  mov ah,0xFF      ;Seta Padrao Para Comandos com caracter de Controle
  OPTCTRL:

  cmp al,0x0D      ; Tecla ENTER / Comando SAIR
  jne OPTENTER
    ret
  OPTENTER:

  cmp al,0x1B      ; Tecla ESCAPE / Comando SAIR
  jne OPTESC
    ret
  OPTESC:

  cmp ax,'>'+0xFF00; Tecla F4 / Comando SALVA FIGURA DE TELA EM ARQUIVO
  jne OPTF4
  OPTF4O:
    call WRITE_FILE
    jmp MENU
  OPTF4:

  cmp ax,';'+0xFF00; Tecla F1 / Comando HELP
  jne OPTF1
  OPTF1O:
    call HELP
    jmp MENU
  OPTF1:

  cmp ax,'R'+0xFF00; Tecla Ins / Comando ESPELHAR
  jne OPT0
  OPT0O:
    call INVERTIMAGE
    jmp MENU
  OPT0:

  cmp ax,'O'+0xFF00; Tecla End / Comando SCROLL DIAGONAL SO
  jne OPT1
  OPT1O:
    call SCROLL_LEFT
    call SCROLL_DOWN
    jmp MENU
  OPT1:

  cmp ax,'P'+0xFF00; Tecla DOWN / Comando SCROLL DIAGONAL S
  jne OPT2
  OPT2O:
    call SCROLL_DOWN
    jmp MENU
  OPT2:

  cmp ax,'Q'+0xFF00; Tecla Pg Dn / Comando SCROLL DIAGONAL SE
  jne OPT3
  OPT3O:
    call SCROLL_RIGHT
    call SCROLL_DOWN
    jmp MENU
  OPT3:

  cmp ax,'K'+0xFF00; Tecla LEFT / Comando SCROLL DIAGONAL O
  jne OPT4
  OPT4O:
    call SCROLL_LEFT
    jmp MENU
  OPT4:

  cmp ax,'L'+0xFF00; Tecla <5> / Comando CENTRALIZAR
  jne OPT5
  OPT5O:
    call CLEANIMAGE
    call RESET_POS
    jmp MENU
  OPT5:

  cmp ax,'M'+0xFF00; Tecla RIGHT / Comando SCROLL DIAGONAL L
  jne OPT6
  OPT6O:
    call SCROLL_RIGHT
    jmp MENU
  OPT6:

  cmp ax,'G'+0xFF00; Tecla Home / Comando SCROLL DIAGONAL NO
  jne OPT7
  OPT7O:
    call SCROLL_LEFT
    call SCROLL_UP
    jmp MENU
  OPT7:

  cmp ax,'H'+0xFF00; Tecla UP / Comando SCROLL DIAGONAL N
  jne OPT8
  OPT8O:
    call SCROLL_UP
    jmp MENU
  OPT8:

  cmp ax,'I'+0xFF00; Tecla Pg Up / Comando SCROLL DIAGONAL NE
  jne OPT9
  OPT9O:
    call SCROLL_RIGHT
    call SCROLL_UP
    jmp MENU
  OPT9:

  cmp ax,'S'+0xFF00; Tecla DEL / Comando LIMPA TELA
  jne OPTVIRG
  OPTVIRGO:
    call CLEANSCREEN
    jmp MENU
  OPTVIRG:

  cmp ax,'A'+0xFF00; Tecla F7 / Comando IMAGEM ANTERIOR
  jne OPTCA
    call BEFORE_IMAGE
    jmp MENU
  OPTCA:

  cmp ax,'B'+0xFF00; Tecla F8 / Comando PROXIMA FIGURA
  jne OPTCB
    call NEXT_IMAGE
    jmp MENU
  OPTCB:

  cmp ax,'D'+0xFF00; Tecla F10 / Comando RECARREGA IMAGEM DO ARQUIVO
  jne OPTCD
    call OPENFILE
    call IMAGEHEAD
    call GRAPHMOD
    call SET_CURSOR
    call LOAD_MAPCOLOR
    call RESET_COLOR
    call LOADIMAGE
    call RESET_POS
    call CLOSEFILE
    call CLEANSCREEN
    jmp MENU
  OPTCD:

  ;Nao Ha mais comandos com CTRL
  mov dx,ax
  and dx,0xFF00
  jz CTRL_END
    xor ax,ax
  CTRL_END:

  ;comparacao com numeros  
  cmp al,'1'; Tecla 1 / Comando SCROLL DIAGONAL SO
  je OPT1O
  cmp al,'2'; Tecla 2 / Comando SCROLL DIAGONAL S
  je OPT2O
  cmp al,'3'; Tecla 3 / Comando SCROLL DIAGONAL SE
  je OPT3O
  cmp al,'4'; Tecla 4 / Comando SCROLL DIAGONAL O
  je OPT4O
  cmp al,'5'; Tecla 5 / Comando CENTRALIZAR
  je OPT5O
  cmp al,'6'; Tecla 6 / Comando SCROLL DIAGONAL L
  je OPT6O
  cmp al,'7'; Tecla 7 / Comando SCROLL DIAGONAL NO
  je OPT7O
  cmp al,'8'; Tecla 8 / Comando SCROLL DIAGONAL N
  je OPT8O
  cmp al,'9'; Tecla 9 / Comando SCROLL DIAGONAL NE
  je OPT9O
  cmp al,'0'; Tecla 0 / Comando ESPELHAR
  je OPT0O
  cmp al,','; Tecla , / Comando LIMPA TELA
  je OPTVIRGO
  cmp al,'.'; Tecla . / Comando LIMPA TELA
  je OPTVIRGO

  cmp al,'+'; Tecla + / Comando ROTACAO DIREITA
  jne OPTSUM
    call CLEANIMAGE
    call ROTATE_RIGHT
    call RESET_POS
    jmp MENU
  OPTSUM:

  cmp al,'-'; Tecla - / Comando ROTACAO ESQUERDA
  jne OPTSUB
    call CLEANIMAGE
    call ROTATE_LEFT
    call RESET_POS
    jmp MENU
  OPTSUB:

  cmp al,'*'; Tecla * / Comando ESCALA DE CINZA/COLORIDO
  jne OPTC
    call GRAYORCOLOR
    call RESET_COLOR
    jmp MENUSI
  OPTC:

  cmp al,'/'; Tecla / / Comando ???
  jne OPTRBAR
    jmp MENUSI
  OPTRBAR:

  ;Transforma em minuscula, para que nao seja case sensitivity
  or ax,0x20

  cmp al,'q'; Tecla Q / Comando SAIR
  jne OPTQ
    ret
  OPTQ:	

  cmp al,'c'; Tecla C / Comando CENTRALIZA
  je OPT5O

  cmp al,'w'; Tecla W / Comando ESPELHAR
  je OPT0O

  cmp al,'m'; Tecla M / Comando CLAREAR
  jne OPTM
    call MORERED
    call MOREGREEN
    call MOREBLUE
    call RESET_COLOR
    jmp MENUSI
  OPTM:

  cmp al,'n'; Tecla N / Comando RESETA TONALIDADES
  jne OPTN
    call TONORMAL_IMAGE
    call RESET_COLOR
    jmp MENUSI
  OPTN:

  cmp al,'b'; Tecla B / Comando ESCURECE
  jne OPTB
    call LESSRED
    call LESSBLUE
    call LESSGREEN
    call RESET_COLOR
    jmp MENUSI
  OPTB:

  cmp al,'t'; Tecla T / Comando AUMENTA VERMELHO
  jne OPTT
    call MORERED
    call RESET_COLOR
    jmp MENUSI
  OPTT:

  cmp al,'y'; Tecla Y / Comando AUMENTA VERDE
  jne OPTY
    call MOREGREEN
    call RESET_COLOR
    jmp MENUSI
  OPTY:

  cmp al,'u'; Tecla U / Comando AUMENTA AZUL
  jne OPTU
    call MOREBLUE
    call RESET_COLOR
    jmp MENUSI
  OPTU:

  cmp al,'g'; Tecla G / Comando REDUZ VERMELHO
  jne OPTG
    call LESSRED
    call RESET_COLOR
    jmp MENUSI
  OPTG:

  cmp al,'h'; Tecla H / Comando REDUZ VERDE
  jne OPTH
    call LESSGREEN
    call RESET_COLOR
    jmp MENUSI
  OPTH:

  cmp al,'j'; Tecla J / Comando REDUZ AZUL
  jne OPTJ
    call LESSBLUE
    call RESET_COLOR
    jmp MENUSI
  OPTJ:

  cmp al,'r'; Tecla R / Comando ROTACAO DIREITA
  jne OPTR
    call CLEANSCREEN
    call ROTATE_RIGHT
    call RESET_POS
    jmp MENU
  OPTR:

  cmp al,'l'; Tecla L / Comando ROTACAO ESQUERDA
  jne OPTL
    call CLEANSCREEN
    call ROTATE_LEFT
    call RESET_POS
    jmp MENU
  OPTL:

  cmp al,'p'; Tecla P / Comando MOSTRAR PALETA DE CORES
  jne OPTP
    call CLEANSCREEN
    call SHOWCOLOR
    ;le tecla
    mov ah,0x08
    int 0x21
    jmp MENU2
  OPTP:

  cmp al,'o'; Tecla O / Comando MOSTRAR PALETA DE CORES DO MODO GRAFICO
  jne OPTO
    call GRAPHMOD
    call SET_CURSOR
    call SHOWCOLOR
    ;le tecla
    mov ah,0x08
    int 0x21
    push ax
    call CLEANSCREEN
    call RESET_COLOR
    pop ax
    jmp MENU2
  OPTO:

  cmp al,'i'; Tecla I / Comando INVERTE CORES
  jne OPTI
    call INVERTCOLOR
    call RESET_COLOR
    jmp MENUSI
  OPTI:

  ;Imprime Mensagem de Erro em cores de destaque
  call INPUT_TEXT
  mov ax,data
  mov ds,ax
  mov ah,0x09
  mov dx,WR_COMMD
  int 0x21

  ;Le Tecla
  mov ah,0x08
  int 0x21
  xor ah,ah

  call RESET_COLOR; Reseta Cores
  call CLEANSCREEN; Limpa Tela
  call SHOWIMAGE;   Mostra Imagem
  jmp MENU2;        Chama Menu sem Atualizacao de Imagem e sem Leitura de Tec.

  ret              ;Para eventuais erros
INVERTIMAGE:;-----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bx,[WIDTH]
  mov cx,[HEIGHT]
  
  mov ax,[SEG_BUFFER]
  mov ds,ax
  xor di,di
  IML:
    mov si,di
    add si,bx
    dec si
    push di

    IML2:
      mov ah,[ds:di]
      mov al,[ds:si]

      mov [ds:di],al
      mov [ds:si],ah

      dec si
      inc di
      
      cmp di,si
      jb IML2

    pop di
    add di,bx

    mov ax,bx
    neg ax
    and ax,0x03
    add di,ax

    dec cx
  jnz IML

  popa
  ret
  





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES BASICAS PARA EXIBICAO DA IMAGEM CENTRALIZADA EM TELA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
COPY_FLNAME:;--------------------------------------------------------------
  pusha
  ;Seta ds para data
  mov ax,data
  mov ds,ax
  ;Seta es para PSP
  mov ax,[PSP]
  mov es,ax
  
  ;Calcula Quantidade de Caracteres
  xor ch,ch
  mov cl,[es:0x80]
  cmp cx,0x30
  ja CP_FLNMERRO
  dec cx
  
  ;Seta Posicoes iniciais
  mov si,0x82
  mov di,FL_NAME
  
  ;Loop de copia do nome do arquivo
  CPFLN:
    mov al,[es:si]
    mov [ds:di],al
    inc si
    inc di
    loop CPFLN
  ;Seta Caracter Final da String
  xor al,al
  mov [ds:di],al

  popa
  ret
  CP_FLNMERRO:
    mov dx,FL_NAME_INV
    mov ah,0x09
    int 0x21
    call END
OPENFILE:;-----------------------------------------------------------------
  pusha

  ;Seta para inicio do PSP
  mov ax,data
  mov ds,ax

  ;Comando de Abertura de Arquivo
  mov ah,0x3d
  mov al,0x00
  
  ;Seta Inicio de String
  mov dx,FL_NAME
  
  ;Abre!
  int 0x21
  
  ;Verificacao de Erro na Abertura
  jnc OK_OPEN 
  call OPENERRO
  OK_OPEN:

  ;Salva o File Handle na memoria para eventuais backups
  mov [FL_HANDLE],ax

  popa
  ret
OPENERRO:;------------------------------------------------------------------
;Exibicao das Mensagens de erro para a abertura de arquivo

  cmp ax,0x02
  je E_FILE_NF
  cmp ax,0x03
  je E_PATH_NF
  cmp ax,0x04
  je E_NHAN_AV
  cmp ax,0x05
  je E_ACCE_DE
  cmp ax,0x0C
  je E_MODE_IN
  jmp E_ERROR_NR
  E_FILE_NF:
    mov dx,FILE_NF
    jmp EXE_ERRO
  E_PATH_NF:
    mov dx,PATH_NF
    jmp EXE_ERRO
  E_NHAN_AV:
    mov dx,NHAN_AV
    jmp EXE_ERRO
  E_ACCE_DE:
    mov dx,ACCE_DE
    jmp EXE_ERRO
  E_MODE_IN:
    mov dx,MODE_IN
    jmp EXE_ERRO
  E_ERROR_NR:
    mov dx,ERROR_NR
  
  EXE_ERRO:
    ;Imprime String de Erro na Tela
    mov ah,0x09
    int 0x21
  jmp END
IMAGEHEAD:;-------------------------------------------------------------------------
  pusha

  ;Recupera Data e o File Handle
  mov ax,data
  mov ds,ax
  mov bx,[FL_HANDLE]

  ;Leitura do Tipo de Arquivo
  mov cx,0x0002
  mov dx,M_COLOR
  mov ah,0x3f
  int 0x21

  ;Checar Tipo de Arquivo
  cmp word [M_COLOR], "BM"
  je OK_IMAGE1
    call WRONGIMAGE
  OK_IMAGE1:

  ;Seek para Ler os tamanho da imagem
  mov ah,0x42
  mov al,0x01
  xor cx,cx
  mov dx,0x10
  int 0x21

  ;Leitura do Comprimento
  mov cx,0x0004
  mov dx,WIDTH
  mov ah,0x3f
  int 0x21

  ;Leitura do Altura
  mov cx,0x0004
  mov dx,HEIGHT
  mov ah,0x3f
  int 0x21

  ;Seek para ler bits/pixel
  mov ah,0x42
  mov al,0x01
  xor cx,cx
  mov dx,0x02
  int 0x21

  ;Leitura dos bits/pixel
  mov cx,0x0002
  mov dx,M_COLOR
  mov ah,0x3f
  int 0x21

  ;Teste dos bits/pixel
  cmp word [M_COLOR], 0x0008
  je OK_IMAGE2
    call WRONGIMAGE
  OK_IMAGE2:

  ;Leitura da compressao
  mov cx,0x0004
  mov dx,M_COLOR
  mov ah,0x3f
  int 0x21

  ;Teste da compressao
  mov ax,word [M_COLOR]
  or ax,word [M_COLOR+2]
  jz OK_IMAGE3
    call WRONGIMAGE
  OK_IMAGE3:

  ;Seek para ler num cores
  mov ah,0x42
  mov al,0x01
  xor cx,cx
  mov dx,0x0C;
  int 0x21

  ;Leitura de num cores
  mov cx,0x0002
  mov dx,NUM_COLOR
  mov ah,0x3f
  int 0x21

  mov di,dx
  mov dx,[di]
  or dx,0x00
  jnz NUM_COLORV
    mov dx,0x100
    mov [di],dx
  NUM_COLORV:

  popa
  ret
WRONGIMAGE:;----------------------------------------------------------------
  ;Re-inicializa DS
  mov  ax, data
  mov  ds, ax
  
  ;Imprime Mensagem de Arquivo Invalido
  mov ah,0x09
  mov dx,WR_IMAGE
  int 0x21
  
  ;Fecha e Sai
  call CLOSEFILE
  jmp END
GRAPHMOD:;------------------------------------------------------------------
  push ax

  ;Seta Modo Grafico de Video pela BIOS
  mov ah,0
  mov al,0x13 ; 320 x 200  256 colors
  int 0x10

  pop ax
  ret
LOAD_MAPCOLOR:;-----------------------------------------------------------------
  pusha
  ;Recupera Data e o File Handle
  mov ax,data
  mov ds,ax
  mov bx,[FL_HANDLE]

  ;Seek para ler map cores
  mov ah,0x42
  xor al,al
  xor cx,cx
  mov dx,0x36
  int 0x21

  ;Leitura do map de cores
  mov ax,[NUM_COLOR]

  mov dx,0x04     ;Calcula o numero de bits da paleta 
  mul dx          ;ja que cada cor sao 4 bits no arquivo
  mov cx,ax

  mov dx,M_COLOR
  mov ah,0x3f
  int 0x21

  popa
  ret
RESET_COLOR:;-------------------------------------------------------------
  pusha

  ;Recupera Data
  mov ax,data
  mov ds,ax

  ;Carrega Mapa de Cores
  mov bx,0x00        ;Indice da Cor
  mov si,M_COLOR     ;Area de Armazenamento do Mapa de Cores
  mov di,[NUM_COLOR] ;Numero Total de Cores ,para servir de contador
  mov dl,0x3F        ;Tonalidade Maxima de Uma Cor
  
  COLORMAP:
    xor ax,ax

    ;Azul
    mov ah,[FTB_IMAGE] ;Fator de Tonalidade da Cor
    
    mov cl,[si]        ;Pega Valor da Memoria
    shr cl,2           ;Shift ( max 255 > max 63)
    
    add cl,ah          ;Soma Fator
    
    ;Verifica Tonalidade Maxima
    cmp cl,dl
    jle COLORM11
      mov cl,0x3f
      jmp COLORM12
    COLORM11:
    
    ;Verifica Tonalidade Minima
    cmp cl,0x00
    jge COLORM12
      xor cl,cl
    COLORM12:
    
    ;Somatorio dos 3 Tons
    add al,cl
    
    ;Anda Ponteiro na Memoria
    inc si
    
    
    ;Verde
    mov ah,[FTG_IMAGE] ;Fator de Tonalidade da Cor
    
    mov ch,[si]        ;Pega Valor da Memoria
    shr ch,2           ;Shift ( max 255 > max 63)
    
    add ch,ah          ;Soma Fator
    
    ;Verifica Tonalidade Maxima
    cmp ch,dl
    jle COLORM21
      mov ch,0x3f
      jmp COLORM22
    COLORM21:
    
    ;Verifica Tonalidade Minima
    cmp ch,0x00
    jge COLORM22
      xor ch,ch
    COLORM22:
    
    ;Somatorio dos 3 Tons
    add al,ch
    
    ;Anda Ponteiro na Memoria
    inc si
    
    
    ;Vermelho
    mov ah,[FTR_IMAGE] ;Fator de Tonalidade da Cor
    
    mov dh,[si]        ;Pega Valor da Memoria
    shr dh,2           ;Shift ( max 255 > max 63)
    
    add dh,ah          ;Soma Fator
    
    ;Verifica Tonalidade Maxima
    cmp dh,dl
    jle COLORM31
      mov dh,0x3f
      jmp COLORM32
    COLORM31:
    
    ;Verifica Tonalidade Minima
    cmp dh,0x00
    jge COLORM32
      xor dh,dh
    COLORM32:
    
    ;Somatorio dos 3 Tons
    add al,dh
    
    ;Anda Ponteiro na Memoria
    inc si

    ;Anda Ponteiro na Memoria para pular valor 0
    inc si

    ;Verificar e gerar escala de cinza
    mov ah,[CHK_COLOR]
    or ah,0
    jz MCOLOR
      ;Tira Media dos 3 Tons
      xor ah,ah
      mov cl,0x03
      div cl
      ;Seta Media como Tons
      mov dh,al
      mov ch,al
      mov cl,al
    MCOLOR:

    ;Verificar e gerar inversao de cores
    mov ah,[CHK_INVER]
    or ah,0
    jz ICOLOR
      ;Nega todos Tons
      not dh
      not ch
      not cl
      ;Limita Tons
      and dh,0x3F
      and ch,0x3F
      and cl,0x3F
    ICOLOR:

    ;Seta Cor no Modo do Video da Bios
    mov ax,0x1010
    int 0x10

    ;Loop
    inc bx
    dec di
    jnz COLORMAP

  popa
  ret
LOADIMAGE:;--------------------------------------------------------------
  pusha

  ;Recupera Data e File Handle
  mov ax,data
  mov ds,ax
  mov bx,[FL_HANDLE]

  ;Calcula Tamanho Total da Paleta de Cores
  mov ax,[NUM_COLOR]
  mov dx,0x04
  mul dx
  mov dx,ax

  ;Seek para inicio da Imagem no Arquivo
  mov ah,0x42
  xor al,al
  xor cx,cx
  add dx,0x0036
  int 0x21

  ;Quantidade menos 1 de bytes a ler
  mov cx,[MAX_BUFFER]

  ;Segmento de Leitura
  mov ax,[SEG_BUFFER]
  mov ds,ax
  
  ;Leitura
  mov ah,0x3F
  xor dx,dx
  int 0x21

  ;Tenta Ler Mais 1 Byte, para Completar 16kB 
  add dx,0xFFFF ;le o ultimo bit
  mov cx,1
  mov ah,0x3F
  int 0x21

  popa
  ret
RESET_POS:;-----------------------------------------------------------------
  pusha

  ;Recuperando Data e Dimensoes da Imagem
  mov ax,data
  mov ds,ax
  mov si,[WIDTH]
  mov di,[HEIGHT]

  ;Calculo da Posicao de Escrita na tela
  
  ;Deslocamento Horizontal
  xor bx,bx
  mov ax,0x0140;320
  cmp ax,si
  jbe WIDB
    sub ax,si
    shr ax,1
    mov bx,ax
  WIDB:

  ;Deslocamento Vertical
  mov cx,0x00C8;200
  cmp cx,di
  jbe HEIB
    sub cx,di
    shr cx,1
    add cx,di
  HEIB:

  ;Calculo do Deslocamento em Memoria (Vetor)
  dec cx
  mov ax,0x0140;320
  xor dx,dx
  mul cx

  add bx,ax

  ;Salva de Deslocamento em Memoria para Inicio de Escrita em Video
  mov [ST_SCREEN],bx


  ;Calculo da Posicao de leitura do Buffer

  ;Dimensoes da Tela
  mov si,0x0140;320
  mov di,0x00C8;200

  ;Deslocamento Horizontal na Imagem
  xor bx,bx
  mov dx,[WIDTH]
  cmp dx,si
  jna WIDL
    mov bx,dx
    sub bx,si
    shr bx,1
  WIDL:

  ;Deslocamento Vertical na Imagem
  xor cx,cx
  mov dx,[HEIGHT]
  cmp dx,di
  jna HEIL
    mov cx,dx
    sub cx,di
    shr cx,1
    ;add cx,di
  HEIL:
  
  ;Transformação do Compŕimento da Imagem em Multiplo de 4
  ;Para efeitos do proximo Calculo
  mov ax,[WIDTH]
  mov dx,ax
  neg dx
  and dx,0x03
  add ax,dx

  ;Calcula Deslocamento de Memoria na Imagem
  xor dx,dx
  mul cx

  add bx,ax

  ;Salva Deslocamento de Memoria para Copia da Imagem
  mov [ST_IMAGE],bx

  popa
  ret
SHOWIMAGE:;-----------------------------------------------------------------
  pusha

  ;Recupera Data
  mov ax,data
  mov ds,ax

  ;Dimensões da Imagem
  mov bx,[WIDTH]
  mov dx,[HEIGHT]

  ;Posicoes de Copia/Cola
  mov di,[ST_IMAGE]
  mov si,[ST_SCREEN]

  ;Segmento de Video
  mov ax,0xA000
  mov es,ax

  ;Segmento de Buffer Principal
  mov ax,[SEG_BUFFER]
  mov ds,ax

  ;Contador do Loop externo, Altura
  mov ax,dx
  SIL1:
    push ax

    ;Contador do loop Interno, Largura
    mov cx,bx

    ;Checa e Troca Largura Invalida (Maior que 320)
    cmp cx,0x140
    jbe SIL2
      mov cx,0x140

    SIL2:
      mov al,[ds:di] ;copia
      mov [es:si],al ;cola
      inc si
      inc di
      loop SIL2

    ;vai para linha de cima, se ainda tiver alguma
    sub si,0x140
    jb SILE
    sub si,bx

    ;pulo dos pixels nulos por naum ser multiplo de 4
    mov ax,bx
    neg ax
    and ax,0x03
    add di,ax

    ;anda parte cortada horizontalmente
    cmp bx,0x140
    jbe SIL1P
      mov ax,bx
      sub ax,0x140
      add di,ax
      add si,ax
    SIL1P:

    pop ax
    dec ax
    jnz SIL1
  jmp SILE2

  SILE:
  pop ax
  SILE2:

  popa
  ret
TEXTMOD:;------------------------------------------------------------------
  push ax

  ;Seta Modo Texto de Video pela BIOS
  mov ah,0
  mov al,0x03 ; 320 x 200  256 colors
  int 0x10

  pop ax
  ret
CLOSEFILE:;-----------------------------------------------------------------
  push ax
  ;Recupera Data
  mov ax,data
  mov ds,ax
  ;Fecha Arquivo
  mov ah,0x3e
  mov bx,[FL_HANDLE]
  int 0x21
  
  pop ax
  ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES BASICAS PARA TOTACAO DE IMAGENS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ROTATE_RIGHT:;-----Rotacao para direita------------------------------------
  pusha
  
  mov ax,data	;Recupera Data
  mov ds,ax
  
  mov ax,[SEG_BUFFER2]		;
  mov es,ax			;
  mov dx,[WIDTH]		;
  mov bp,[HEIGHT]		;
  mov bx,[SEG_BUFFER]		;

  mov [WIDTH],bp		; Atualiza (inverte) as dimensoes correspondentes a
  mov [HEIGHT],dx		; altura e comprimento para a imgem rotacionada
  mov [SEG_BUFFER],ax		; Inverte o estado dos buffers utilizados, ie,
  mov [SEG_BUFFER2],bx		; o buffer primario eh setado como secundario e vice-versa

  mov ds,bx
  mov bx,dx

  ;Calcula Posicao de inicio de copia
  mov si,dx
  dec si
  xor di,di
;--for HEIGHT do------------------------------------------
  RRLE:
    push si
    ;--for WIDTH do---------------------------------------
    mov cx,bp
    RRLI:
      xor al,al		; Aloca no segundo buffer o resultado da transformacao
      mov ah,[ds:si]	; aplicada ao primeiro buffer 
      mov [ds:si],al	; buffer1: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 
      mov [es:di],ah	; buffer2: 7 | 4 | 1 | 8 | 5 | 2 | 9 | 6 | 3 

      add si,dx

      mov ax,dx		;
      neg ax		; Complementa o numero de bits da colunas 
      and ax,0x03	; para que esta seja multipla de 4
      add si,ax		;

      inc di

      loop RRLI
      ;---------------------------------------------------------
    pop si
    dec si

    mov ax,bp		; 
    neg ax		; Complementa o numero de bits da linhas
    and ax,0x03		; para que esta seja multipla de 4
    add di,ax		;

    dec bx
    jnz RRLE
;---------------------------------------------------------------
  popa
  ret
ROTATE_LEFT:;-----Rotacao para a esquerda----------------------------
  pusha
  
  mov ax,data
  mov ds,ax
  
  mov ax,[SEG_BUFFER2]
  mov es,ax
  mov dx,[WIDTH]
  mov bp,[HEIGHT]
  mov bx,[SEG_BUFFER]

  mov [WIDTH],bp		; Atualiza as dimensoes correspondentes a
  mov [HEIGHT],dx		; altura e comprimento para a imagem rotacionada
  mov [SEG_BUFFER],ax		; Inverte os estados dos buffers utilizados, ie,
  mov [SEG_BUFFER2],bx		; o buffer primario eh setado como secundario e vice-versa

  mov ds,bx

  ;Calcula Posicao de inicio de copia
  push dx

  mov ax,bp
  dec ax
  mov bx,dx
  neg bx
  and bx,0x03
  add bx,dx
  xor dx,dx
  mul bx
  mov si,ax			; si contem o offset da ultima posicao do buffer
				; que recebe a imagem rotacionada
  pop dx

  mov bx,dx
  xor di,di
;---for HEIGTH do--------------------------------------------------
  RLLE:
    push si
    ;---for WIDTH do-----------------------------------------------
    mov cx,bp
    RLLI:
      xor al,al			; Aloca no segundo buffer o resultado da transformacao 
      mov ah,[ds:si]		; aplicada ao primeiro buffer
      mov [ds:si],al		; buffer1: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 
      mov [es:di],ah		; buffer2: 3 | 6 | 9 | 2 | 5 | 8 | 1 | 4 | 7

      sub si,dx

      mov ax,dx			; 
      neg ax			; Complementa o numero de bits das colunas
      and ax,0x03		; para que estas sejam multiplas de 4
      sub si,ax			;

      inc di

      loop RLLI
    ;----------------------------------------------------------------
    pop si
    inc si

    mov ax,bp			;
    neg ax			; Complemanta o numero de bits das linhas
    and ax,0x03			; para que estas sejam multiplas de 4
    add di,ax			;

    dec bx
    jnz RLLE
;------------------------------------------------------------------
  popa
  ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; A funcoes abaixo deste ponto nao foram devidamente comentadas devido ao fato de falta de
; tempo perante a entrega desde programa, uma vez que muita parte do tempo foi gasta no 
; desenvolvimento destas funcoes de modo opcional

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES BASICAS PARA SCROLL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SCROLL_LEFT:;--------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov cx,[WIDTH]
  cmp cx,0x140
  jae SLMIP
  xor dx,dx
  mov di,[ST_SCREEN]

  mov ax,di
  xor dx,dx
  mov si,0x140
  div si
  or dx,0
  jz SLE

  dec di
  mov ax,di  
  mov dx,cx
  add di,dx
  cmp dx,cx
  ja SLEP
    sub dx,cx
    sub di,dx
  SLEP:
  
  mov ax,0xA000
  mov es,ax
  xor dx,dx
  mov cx,[HEIGHT]

  SLEL:
    mov [es:di],dl
    sub di,0x140
    dec cx
    jnz SLEL
  mov ax,[ST_SCREEN]
  dec ax
  mov [ST_SCREEN],ax
  jmp SLE

  SLMIP:
  xor dx,dx
  mov ax,[ST_IMAGE]
  mov bx,ax
  mov cx,[WIDTH]
  div cx
  sub cx,0x140
  cmp dx,cx
  je SLE
    inc bx
    mov [ST_IMAGE],bx
  SLE:
  popa
  ret
SCROLL_RIGHT:;--------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bp,[WIDTH]
  cmp bp,0x140
  jae SRMPI
  mov cx,[HEIGHT]
  mov ax,0xA000
  mov es,ax
  mov di,[ST_SCREEN]
  mov ax,di
  xor dx,dx
  mov si,0x140
  div si
  add dx,bp
  dec dx
  cmp dx,0x13F
  je SRE
  xor dx,dx
  SRIL:
    mov [es:di],dl
    sub di,0x140
    dec cx
    jnz SRIL

  mov ax,[ST_SCREEN]
  inc ax
  mov [ST_SCREEN],ax
  jmp SRE
  SRMPI:
  xor dx,dx
  mov ax,[ST_IMAGE]
  mov bx,ax
  mov cx,[WIDTH]
  div cx
  or dx,0
  jz SRE
    dec bx
    mov [ST_IMAGE],bx
  SRE:
  popa
  ret
SCROLL_DOWN:;--------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov cx,[HEIGHT]
  cmp cx,0xC8
  jae SDMPI
  dec cx
  mov ax,0xA000
  mov es,ax
  xor dx,dx
  mov di,[ST_SCREEN]
  cmp di,0xF8C0
  jae SDE
  SDNLP:
    sub di,0x140
    dec cx
    jnz SDNLP


  mov cx,[WIDTH]

  SDNL:
    mov [es:di],dl
    inc di
    dec cx
    jnz SDNL

  mov ax,[ST_SCREEN]
  add ax,0x0140;320
  mov [ST_SCREEN],ax
  jmp SDE

  SDMPI:
  mov ax,[HEIGHT]
  sub ax,0xC8
  mov bx,[WIDTH]
  mul bx
  mov di,[ST_IMAGE]
  cmp di,ax
  jae SDE
  add di,bx
  mov ax,bx
  neg ax
  and ax,0x03
  add di,ax
  mov [ST_IMAGE],di
  SDE:
  popa
  ret
SCROLL_UP:;--------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov dx,[HEIGHT]
  mov cx,[WIDTH]
  cmp dx,0xC8
  jae SUMIP

  mov ax,0xA000
  mov es,ax

  mov di,[ST_SCREEN]
  mov ax,0x140

  mul dx
  cmp di,ax
  jb SUE
  xor dx,dx
  SUPL:
    mov [es:di],dl
    inc di
    dec cx
    jnz SUPL

;nova posicao
  mov ax,[ST_SCREEN]
  sub ax,0x0140;320
  mov [ST_SCREEN],ax

SUMIP:
  mov bx,[WIDTH]
  mov di,[ST_IMAGE]
  cmp di,bx
  jb SDE
  sub di,bx
  mov ax,bx
  neg ax
  and ax,0x03
  sub di,ax
  mov [ST_IMAGE],di

SUE:
  popa
  ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES PARA LIMPEZA DE TELA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CLEANSCREEN:;-----------------------------------------------------------------
  pusha

  mov bx,0xA000
  mov es,bx
  mov cx,0xFA00
  xor bx,bx
  xor dx,dx
  CSCREEN:
    mov [es:bx],dl
    inc bx
    dec cx
    jnz CSCREEN

  popa
  ret
CLEANIMAGE:;-----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov si,[WIDTH]
  mov dx,[HEIGHT]
  mov bx,[ST_SCREEN]
  mov ax,0xA000
  mov es,ax

  mov ax,dx
  CIL1:
    push ax
    mov cx,si
    xor al,al
    CIL2:
      mov [es:bx],al
      inc bx
      inc di
      loop CIL2
    sub bx,0x140;320
    jb CILE
    sub bx,si

    mov ax,si
    neg ax
    and ax,0x03
    add di,ax

    pop ax
    dec ax
    jnz CIL1
  CILE:

  popa
  ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES PARA MANIPULACAO DE CORES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GRAYORCOLOR:;----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov dl,[CHK_COLOR]
  not dl
  mov [CHK_COLOR],dl

  popa
  ret
TONORMAL_IMAGE:;-----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  xor dl,dl
  mov [FTR_IMAGE],dl
  mov [FTG_IMAGE],dl
  mov [FTB_IMAGE],dl

  popa
  ret
MORERED:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0x3F

  mov dl,[FTR_IMAGE]
  cmp dl,bl
  je MRED1
  inc dl
  mov [FTR_IMAGE],dl
  MRED1:

  popa
  ret
MOREBLUE:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0x3F

  mov dl,[FTB_IMAGE]
  cmp dl,bl
  je MBLUE1
  inc dl
  mov [FTB_IMAGE],dl
MBLUE1:

  popa
  ret
MOREGREEN:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0x3F

  mov dl,[FTG_IMAGE]
  cmp dl,bl
  je MGREEN1
  inc dl
  mov [FTG_IMAGE],dl
MGREEN1:

  popa
  ret
LESSRED:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0xC1

  mov dl,[FTR_IMAGE]
  cmp dl,bl
  je LRED1
  dec dl
  mov [FTR_IMAGE],dl
LRED1:

  popa
  ret
LESSBLUE:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0xC1

  mov dl,[FTB_IMAGE]
  cmp dl,bl
  je LBLU1
  dec dl
  mov [FTB_IMAGE],dl
LBLU1:

  popa
  ret
LESSGREEN:;---------------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov bl,0xC1

  mov dl,[FTG_IMAGE]
  cmp dl,bl
  je LGRE1
  dec dl
  mov [FTG_IMAGE],dl
LGRE1:

  popa
  ret
INVERTCOLOR:;-----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov dl,[CHK_INVER]
  not dl
  mov [CHK_INVER],dl

  popa
  ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES PARA EXIBICAO EM TELA DE FUNCOES EXTRAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SET_CURSOR:;------------------------------------------------------------------
  pusha
  mov cx,0x18
  mov ah,0x02
  mov dl,0x0A
  SCUL:
    int 0x21
    loop SCUL
  popa
  ret
INPUT_TEXT:;------------------------------------------------------------------
  pusha
    mov ax,0x1010
    xor bx,bx
    xor cx,cx
    xor dx,dx
    int 0x10
    mov ax,0x1010
    mov bx,0x0f
    mov dh,0x3F
    int 0x10
  popa
  ret
SHOWCOLOR:;-----------------------------------------------------------------
  pusha

  mov ax,data
  mov ds,ax

  mov si,0x140 ;320
  mov dx,0xc8  ;200

  mov di,[NUM_COLOR]

  mov ax,0xA000
  mov es,ax

  xor bx,bx
  SCL:
    mov cx,di
    SCLL:
      mov [es:bx],cx
      inc bx
      loop SCLL
    add bx,si
    sub bx,di
    dec dx
    jnz SCL

  popa
  ret
HELP:;------------------------------------------------------------------------
  pusha
  call CLEANSCREEN
  call TEXTMOD
  mov ax,data
  mov ds,ax
  mov ah,0x09
  mov dx,HELP_M
  int 0x21
  
  mov ah,0x08
  int 0x21
  xor ah,ah

  call GRAPHMOD
  call SET_CURSOR
  call RESET_COLOR
  call CLEANSCREEN
  popa
  ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OPERAÇÕES PARA MANIPULACAO EXTRA DE ARQUIVOS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WRITE_FILE:;------------------------------------------------------------------
  pusha
  mov ax,data
  mov ds,ax
  mov es,ax
  call OPENFILE
  ;Cria Arquivo
  mov ah,0x3C
  xor cx,cx
  mov dx,SV_FILE
  int 0x21

  jnc NWFER1
  jmp WFER
  NWFER1:
  ;Fecha
  mov bx,ax
  mov ah,0x3e
  int 0x21

  ;Comando de Abertura
  mov ah,0x3d
  mov al,0x01
  mov dx,SV_FILE
  int 0x21
  jnc NWFER2
  jmp WFER
  NWFER2:
  mov bp,ax
  
  push ds
  mov ax,[SEG_BUFFER2]
  mov ds,ax
  
  mov ah,0x3f
  mov bx,[es:FL_HANDLE]
  mov cx,0x12
  xor dx,dx
  int 0x21
  
  ;escreve file header
  mov ah,0x40
  mov bx,bp
  int 0x21

  pop ds

  ;comprimento
  mov cx,0x02
  mov dx,WIDTH
  mov ah,0x40
  mov bx,bp
  int 0x21
  add dx,0x02
  mov ah,0x40
  mov bx,bp
  int 0x21

  ;altura
  mov cx,0x02
  mov dx,HEIGHT
  mov ah,0x40
  mov bx,bp
  int 0x21
  add dx,0x02
  mov ah,0x40
  mov bx,bp
  int 0x21


  push ds
  mov ax,[SEG_BUFFER2]
  mov ds,ax

  ;Seek
  mov ah,0x42
  mov al,0x01
  mov bx,[es:FL_HANDLE]
  xor cx,cx
  mov dx,0x08;
  int 0x21

  ;Le Image Header
  mov ah,0x3f
  mov cx,0x1C
  xor dx,dx
  int 0x21
  ;escreve iamge header
  mov ah,0x40
  mov bx,bp
  int 0x21
  
  ;copia map color
  mov di,[es:NUM_COLOR]
  xor bx,bx
  mov [3],bl
  WFMC:
    mov ax,0x1015
    int 0x10
    inc bx
    push bx
    shl cl,2
    shl ch,2
    shl dh,2
    mov [0],cl
    mov [1],ch
    mov [2],dh
    mov ah,0x40
    mov cx,0x04
    mov bx,bp
    xor dx,dx
    int 0x21
    pop bx
    dec di
    jnz WFMC

  mov ax,[es:WIDTH]
  mov bx,ax
  neg bx
  and bx,0x03
  add ax,bx
  xor dx,dx
  mov cx,[es:HEIGHT]
  mul cx
  mov cx,ax
  mov ax,[es:SEG_BUFFER]
  mov ds,ax
  xor dx,dx
  mov ah,0x40
  mov bx,bp
  int 0x21

  pop ds
  jmp WFE
  WFER:
  call INPUT_TEXT
  mov ax,data
  mov ds,ax
  mov ah,0x09
  mov dx,SV_ERROR
  int 0x21
  WFE:
  call CLOSEFILE
  ;Seta Comando
  mov ah,0x3e
  mov bx,bp
  ;Executa
  int 0x21
  popa
  ret
NEXT_IMAGE:;------------------------------------------------------------------
  pusha
  mov ax,data
  mov ds,ax
  
  mov si,EFL_NAME
  mov bl,'.'
  mov cl,0x24
  NIL:
    mov dl,[si]
    cmp dl,bl
    je NILE
    cmp dl,cl
    je NIERROR
    dec si
    jmp NIL
  NILE:
  dec si
  mov bl,[si]
  cmp bl,0x30
  jb NIERROR
  cmp bl,0x39
  ja NIERROR
  inc bl
  cmp bl,0x3A
  jne NI1
    mov bl,0x30
    mov [si],bl
    dec si
    mov bl,[si]
    cmp bl,0x30
    jb NIERROR
    cmp bl,0x39
    jae NIERROR
    inc bl
  NI1:
  mov [si],bl

  call TEXTMOD
  call OPENFILE
  call IMAGEHEAD
  call GRAPHMOD
  call SET_CURSOR
  call LOAD_MAPCOLOR
  call RESET_COLOR
  call LOADIMAGE
  call RESET_POS
  call CLOSEFILE
  call CLEANSCREEN

  NIERROR:
  popa
  ret
BEFORE_IMAGE:;------------------------------------------------------------------
  pusha
  mov ax,data
  mov ds,ax
  
  mov si,EFL_NAME
  mov bl,'.'
  mov cl,0x24
  BIL:
    mov dl,[si]
    cmp dl,bl
    je BILE
    cmp dl,cl
    je BIERROR
    dec si
    jmp BIL
  BILE:
  dec si
  mov bl,[si]
  cmp bl,0x30
  jb BIERROR
  cmp bl,0x39
  ja BIERROR
  dec bl
  cmp bl,0x2F
  jne BI1
    mov bl,0x39
    mov [si],bl
    dec si
    mov bl,[si]
    cmp bl,0x30
    jbe BIERROR
    cmp bl,0x39
    ja BIERROR
    dec bl
  BI1:
  mov [si],bl

  call TEXTMOD
  call OPENFILE
  call IMAGEHEAD
  call GRAPHMOD
  call SET_CURSOR
  call LOAD_MAPCOLOR
  call RESET_COLOR
  call LOADIMAGE
  call RESET_POS
  call CLOSEFILE
  call CLEANSCREEN

  BIERROR:
  popa
  ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FINALIZACAO DE EXECUCAO DO PROGRAMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END:;------------------------------------------------------------------------
  mov  ah, 0x4C             ; volta controle ao DOS
  int  0x21

align 16
SEGMENT data; segmento de dados ----------------------------------------------
;Mensagens
FL_NAME_INV: db "File Name Invalid",0x0D,0x24
SV_ERROR: db "Save Error",0x0D,0x24
WR_COMMD: db "Not Accepted Command",0x0D,0x24
FILE_NF: db "File not Found",0x0D,0x0A,0x24
PATH_NF: db "Path not Found",0x0D,0x0A,0x24
NHAN_AV: db "No handle available",0x0D,0x0A,0x24
ACCE_DE: db "Access Denied",0x0D,0x0A,0x24
MODE_IN: db "Open Mode Invalid",0x0D,0x0A,0x24
ERROR_NR: db "Error Not Recognized",0x0D,0x0A,0x24
WR_IMAGE: db "Not Accepted Image",0x0D,0x0A,0x24
HELP_M:
db "Programa em Assembly NASM para Visualizacao de BMP",0x0D,0x0A
db "O Bitmap deve possuir maximo de 256 cores, sem Compactacao, max de 64k pixels",0x0D,0x0A
db "Execucao: BMP XXXXNN.bmp",0x0D,0x0A
db "Onde NN eh um numero de 00 a 99",0x0D,0x0A,0x0D,0x0A
db "Ajuda",0x09,0x09,0x09,"<F1>",0x0D,0x0A
db "Sair",0x09,0x09,0x09,"Q <ENTER> <ESC>",0x0D,0x0A
db "Navegacao",0x09,0x09,"<F7> <F8>",0x0D,0x0A
db "Rotacao D",0x09,0x09,"R +",0x0D,0x0A
db "Rotacao E",0x09,0x09,"L -",0x0D,0x0A
db "Scroll",0x09,0x09,0x09,"Teclado Numerico",0x0D,0x0A
db "Centralizar",0x09,0x09,"C 5",0x0D,0x0A
db "Clarear",0x09,0x09,0x09,"M",0x0D,0x0A
db "Escurecer",0x09,0x09,"B",0x0D,0x0A
db "Vermelho",0x09,0x09,"T G",0x0D,0x0A
db "Verde",0x09,0x09,0x09,"Y H",0x0D,0x0A
db "Azul",0x09,0x09,0x09,"U J",0x0D,0x0A
db "Tons Normais",0x09,0x09,"N",0x0D,0x0A
db "Negativo",0x09,0x09,"I",0x0D,0x0A
db "Esc. Cinza",0x09,0x09,"*",0x0D,0x0A
db "Espelhamento",0x09,0x09,"W 0 <INS>",0x0D,0x0A
db "Paleta Cores",0x09,0x09,"P",0x0D,0x0A
db "Paleta Cores*",0x09,0x09,"O",0x0D,0x0A
db "Reload Arq.",0x09,0x09,"<F10>",0x0D,0x0A
db "Salva MOD File",0x09,"<F4>",0x0D,0x24


;Mapa de Cores
NUM_COLOR: resb 0x02     ;Numero de Cores Usadas
M_COLOR: resb 0x400      ;Mapa de Cores na Memoria

;Nome de Arquivos
SV_FILE: db "mod"        ;Variante para Salvar Arquivo
FL_NAME: resb 0x30       ;Nome do Arquivo
EFL_NAME: db 0x00        ;final do Nome do Arquivo

;Backups
PSP: resb 0x02           ;Endereco de Segmento Inicial do Arquivo
FL_HANDLE: resb 0x02     ;File Handle

;Buffers
WIDTH: resb 0x04         ;Comprimento da Figura no Buffer atual
HEIGHT: resb 0x04        ;Altura da Figura no Buffer atual

ST_SCREEN: resb 0x02     ;Inicio da Cola da Imagem na Tela
ST_IMAGE: resb 0x02      ;Inicio de Copia da Imagem para a Tela

CHK_COLOR: db 0x00       ;Colorido/Cinza
CHK_INVER: db 0x00       ;Inverte ou não as cores
FTR_IMAGE: db 0x00       ;Variacao do Vermelho
FTG_IMAGE: db 0x00       ;Variacao do verde
FTB_IMAGE: db 0x00       ;Variacao do azul

SEG_BUFFER: resb 0x02    ;Segmento de Buffer sendo Utilizado no momento
SEG_BUFFER2: resb 0x02   ;Segmento de Buffer em modo Secundario

MAX_BUFFER: dw 0xFFFF    ;tamanho maximo dos buffers -1

align 16
SEGMENT segbuffer; segmento de buffer ----------------------------------------------
BUFFER: resb 0x10000

align 16
SEGMENT segbuffer2; segmento de buffer ----------------------------------------------
BUFFER2: resb 0x10000

SEGMENT stack stack        ; segmento de pilha
  RESB 256
stacktop:
